/**
  ******************************************************************************
  * @file    usb2can_driver.c
  * @author  vincent
  * @version V1.0.0
  * @date    2018/10/09
  * @brief   This file summary is to provide some interfaces for can2usb 
  ******************************************************************************
  * @attention
  *
  * 
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include "usb2can_driver.h"

/* prama define discrible -----------------------------------------------------*/


/* strcuct  discrible --------------------------------------------------------*/


/* prama  discrible ----------------------------------------------------------*/


/* private fucntion  declaration ---------------------------------------------*/

void*  can_recive_thread(void*param);


/******************************************************************************
* @Function:  can_device device_can_init(void)
* @Discrible: can device initial
* @Param:  
* @Return:   
* @Others: 
******************************************************************************
* @Recode    date       version	        author             modify 
*          ------------------------------------------------------------------
*          20181009      V1.0          VINCENT            Create
* 
*******************************************************************************/
can_device device_can_init(void)
{
    can_device default_device ={0};

    INIT_CONFIG config;
    config.AccCode = 0;
    config.AccMask = 0xffffffff;
    config.Filter = 0;
    config.Mode = 0;
    config.Timing0 = kbps_1000 & 0xff;
    config.Timing1 = kbps_1000 >> 8;
    
    default_device.device_type = can2usb_i;
    default_device.device_index = 0;
    default_device.can_channel = 0;
    default_device.can_config = config;

    return default_device;
}

/******************************************************************************
* @Function:  function device_can_open(can_device device_name)
* @Discrible:   
* @Param:  
* @Return:   
* @Others: 
******************************************************************************
* @Recode    date       version	        author             modify 
*          ------------------------------------------------------------------
*          20181009      V1.0          VINCENT            Create
* 
*******************************************************************************/
function device_can_open(can_device device_name, unsigned int* err_code)
{
    DWORD dwRel = 0;
    ERR_INFO err_info;
    *err_code = 0;

    /* 延时1s，防止设备未准备好*/
    sleep(1);
    if(USBCAN1 == device_name.device_type)
    {  
        do
        {
            /* 延时500ms，防止设备未准备好*/
            sleep(0.5);
            dwRel = OpenDevice(device_name.device_index,device_name.device_index,0);
            if(dwRel == STATUS_OK)
            {
                break;
            }
            else
            {
                if(!ReadErrInfo(device_name.device_index, device_name.device_index, device_name.can_index, &err_info))
                {
                    printf("设备打开失败，并且无法读取失败信息！\n");
                    *err_code = (unsigned int)err_info.ErrCode;
                    return err_code_null;
                }

                /*如果设备不存在，则直接返回*/
                if((err_info.ErrCode&(0x1000))||(err_info.ErrCode&(0x0200)))
                {
                    printf("设备不存在！\n");
                    *err_code = (unsigned int)err_info.ErrCode;
                    return err_code_no_device;
                }
                /*其他错误继续重新打开*/
                if(err_info.ErrCode&(0x0100))
                {   
                    CloseDevice(device_name.device_type, device_name.device_index);
                }                
                else if(err_info.ErrCode&(0x0400))
                {
                     printf("设备没打开！\n");
                }
            }          
        }while(dwRel != STATUS_OK);
        
        printf("打开设备chenggong!\n");

        dwRel = InitCAN(device_name.device_type, device_name.device_index,device_name.can_index, &device_name.can_config);

        if(dwRel != STATUS_OK)
        {
            printf("初始化设备失败!\n");
            return statu_err;
        }
        printf("初始化设备成功!\n");

        dwRel = StartCAN(device_name.device_type, device_name.device_index,device_name.can_index);

        if(dwRel != STATUS_OK)
        {
            printf("设备开始失败!\n");
            return statu_err;
        }    
        printf("-------------------设备开始工作--------------------\n");

        /*开始接受数据时，清空缓存0*/
        ClearBuffer(device_name.device_type, device_name.device_index,device_name.can_index);
        
    }
    else
    {
        printf("当前只支持USBCANI\n");
        return statu_err;
    }

    return statu_ok;
}


/******************************************************************************
* @Function:  
* @Discrible:   
* @Param:  
* @Return:   
* @Others: 
******************************************************************************
* @Recode    date       version	        author             modify 
*          ------------------------------------------------------------------
*          20181009      V1.0          VINCENT            Create
* 
*******************************************************************************/
function device_can_config(can_device device_name)
{

}


/******************************************************************************
* @Function:  
* @Discrible:   
* @Param:  
* @Return:   
* @Others: 
******************************************************************************
* @Recode    date       version	        author             modify 
*          ------------------------------------------------------------------
*          20181009      V1.0          VINCENT            Create
* 
*******************************************************************************/
function device_can_info_get(can_device device_name)
{

}


/******************************************************************************
* @Function:  
* @Discrible:   
* @Param:  
* @Return:   
* @Others: 
******************************************************************************
* @Recode    date       version	        author             modify 
*          ------------------------------------------------------------------
*          20181009      V1.0          VINCENT            Create
* 
*******************************************************************************/
function device_can_close(can_device device_name)
{
    DWORD dwRel = 0;
    if(USBCAN1 == device_name.device_type)
    {  
        dwRel = CloseDevice(device_name.device_type, device_name.device_index);
        if(dwRel != STATUS_OK)
        {
            printf("关闭设备失败!\n");
            return statu_err;
        }
    }
    else
    {
        printf("当前只支持USBCANI\n");
        return statu_err;
    }

    return statu_ok;
}



/******************************************************************************
* @Function:  
* @Discrible:   
* @Param:  
* @Return:   This file provides  functions.
* @Others: 
******************************************************************************
* @Recode    date       version	        author             modify 
*          ------------------------------------------------------------------
*          20181009      V1.0          VINCENT            Create
* 
*******************************************************************************/
function device_can_write_msg(can_device device_name,can_msg_package* tx_msg_package)
{ 
    unsigned int i = 0;
    
    can_msg_package* tx_msg = tx_msg_package;
    /* 发送缓冲区1K = 128×8 */
    if(tx_msg->total_count > CAN_RX_MSG_BUF)
    {       
        return statu_err;
    }
    else if(tx_msg->total_count == 0)
    {
        return statu_ok;
    }
    else
    {      
        /*完整帧装载*/
        for(i = 0; i < tx_msg->total_count; i++)
        {
            device_name.can_tx_obj[i].ID = tx_msg->can_msg_buf->id;
            device_name.can_tx_obj[i].ExternFlag = 0;
            device_name.can_tx_obj[i].RemoteFlag = 0;
            device_name.can_tx_obj[i].SendType = 0;
            device_name.can_tx_obj[i].TimeFlag = 0;
            device_name.can_tx_obj[i].TimeStamp = 0;
            device_name.can_tx_obj[i].DataLen = tx_msg->can_msg_buf[i].len;
           
        }       
        /*完整帧发送（按照手册，Transmit可以发送多帧，但实测测试过程中，多帧时会丢帧，而且每次都是3帧就丢，
        怀疑时三级缓存满了，所以在这里采用单帧发送的方式）*/
        for (i = 0; i < tx_msg->total_count; i++)
        {          
            memcpy(device_name.can_tx_obj[i].Data,&tx_msg->can_msg_buf->msg[i],tx_msg->can_msg_buf[i].len);
            Transmit(device_name.device_type, device_name.device_index, device_name.can_index, &device_name.can_tx_obj[i],1);
        }       
    }
    return statu_ok;
}

/******************************************************************************
* @Function:  
* @Discrible:   
* @Param:  
* @Return:   This file provides  functions.
* @Others: 
******************************************************************************
* @Recode    date       version	        author             modify 
*          ------------------------------------------------------------------
*          20181009      V1.0          VINCENT            Create
* 
**********************************CAN_RX_MSG_BUF*********************************************/
function device_can_write_buffer(can_device device_name,unsigned int msg_id, unsigned char*buf,unsigned int length)
{ 
    unsigned int package_count = 0;
    unsigned int package_left = 0;
    unsigned int i = 0;

    /*计算发送数据包需要多少帧报文才能发送完*/
    package_count = length/8;
    package_left = length%8;
    
    /*完整帧装载*/
    for(i = 0; i < package_count; i++)
    {
        device_name.can_tx_obj[i].ID = msg_id;
        device_name.can_tx_obj[i].ExternFlag = 0;
        device_name.can_tx_obj[i].RemoteFlag = 0;
        device_name.can_tx_obj[i].SendType = 0;
        device_name.can_tx_obj[i].TimeFlag = 0;
        device_name.can_tx_obj[i].TimeStamp = 0;
        device_name.can_tx_obj[i].DataLen = 8;
    }
    
    /*完整帧发送（按照手册，Transmit可以发送多帧，但实测测试过程中，多帧时会丢帧，而且每次都是3帧就丢，
    怀疑时三级缓存满了，所以在这里采用单帧发送的方式）*/
    for (i = 0; i < package_count; i++)
    {
      memcpy(device_name.can_tx_obj[i].Data,buf+i*8,8);
       Transmit(device_name.device_type, device_name.device_index, device_name.can_index, &device_name.can_tx_obj[i],1);
    }
   
    /*不足帧发送*/
    if( package_left > 0)
    {
        device_name.can_tx_obj[package_count].ID = msg_id;       
        device_name.can_tx_obj[package_count].DataLen = package_left; 
        memcpy(device_name.can_tx_obj[package_count].Data,buf+package_count*8,package_left);
        Transmit(device_name.device_type, device_name.device_index, device_name.can_index, &device_name.can_tx_obj[package_count], 1);       
    }

    return statu_ok;
}


/******************************************************************************
* @Function:  function device_can_read_msg(can_device device_name,can_msg_package* tx_msg_package)
* @Discrible:   
* @Param:  
* @Return:   
* @Others: 
******************************************************************************
* @Recode    date       version	        author             modify 
*          ------------------------------------------------------------------
*          20181009      V1.0          VINCENT            Create
* 
*******************************************************************************/
function device_can_read_msg(can_device device_name,can_msg_package* tx_msg_package)
{
    static int taotal_count = 0;
    int rec_cnt; // current received
    int i = 0;
    
    tx_msg_package->total_count = Receive(device_name.device_type, device_name.device_index, 
                    device_name.can_index, device_name.can_rx_obj, 100, 10); 
    /*无数据，直接返回*/
    if(tx_msg_package->total_count == 0)
    {
        return statu_ok;
    }
    
    /*防止缓存溢出*/
    if(tx_msg_package->total_count > CAN_RX_MSG_BUF)
    {
        tx_msg_package->total_count =  CAN_RX_MSG_BUF;      
    }
   
    //tx_msg_package->total_count = rec_cnt;
    /*数据接收*/
    for(i = 0; i < tx_msg_package->total_count; i++)
    {
        /* 只接受标准帧*/
        if((device_name.can_rx_obj[i].ExternFlag != 0) && (device_name.can_tx_obj[i].RemoteFlag != 0) 
            && (device_name.can_tx_obj[i].SendType != 0))
        {
            continue;
        }
        tx_msg_package->can_msg_buf[i].id = device_name.can_rx_obj[i].ID;
        tx_msg_package->can_msg_buf[i].len = device_name.can_rx_obj[i].DataLen;
        memcpy(&tx_msg_package->can_msg_buf[i].msg,device_name.can_rx_obj[i].Data,device_name.can_rx_obj[i].DataLen);
    }

    taotal_count = taotal_count + tx_msg_package->total_count;
    printf("\r\n-----------recive: %d   %d----------\r\n", rec_cnt,taotal_count);
  
  /*暂不考虑多线程情况*/
  /*  
   pthread_t rx_threads;
   pthread_create(&rx_threads, NULL, can_recive_thread, &device_name);
   void *recycle;  //线程结束时，存放回收的数据  
   pthread_join(rx_threads,&recycle); //回收资源  */
   return statu_ok;
}




/* private fucntion  discrible -----------------------------------------------*/
/******************************************************************************
* @Function:  
* @Discrible:   
* @Param:  
* @Return:   
* @Others: 
******************************************************************************
* @Recode    date       version	        author             modify 
*          ------------------------------------------------------------------
*          20181009      V1.0          VINCENT            Create
* 
*******************************************************************************/
void* can_recive_thread(void*param)
{ 
    int cnt; // current received
    CAN_OBJ can[100]; // buffer
       
    can_device device_name_rec = *(can_device*)param;
    cnt = Receive(device_name_rec.device_type, device_name_rec.device_index, 
                    device_name_rec.can_index, can, 100, 10);   
}


/************************ (C) END OF FILE ************************************/




